package com.example.houseitemmanagebackend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.houseitemmanagebackend.dto.CaptchaDTO;
import com.example.houseitemmanagebackend.dto.LoginDTO;
import com.example.houseitemmanagebackend.dto.PasswordDTO;
import com.example.houseitemmanagebackend.dto.RegisterDTO;
import com.example.houseitemmanagebackend.dto.UserProfileDTO;
import com.example.houseitemmanagebackend.dto.ResetPasswordDTO;
import com.example.houseitemmanagebackend.dto.ChangePasswordDTO;
import com.example.houseitemmanagebackend.entity.Role;
import com.example.houseitemmanagebackend.entity.UserLocation;
import com.example.houseitemmanagebackend.entity.Users;
import com.example.houseitemmanagebackend.entity.UserRole;
import com.example.houseitemmanagebackend.exception.BusinessException;
import com.example.houseitemmanagebackend.mapper.RoleMapper;
import com.example.houseitemmanagebackend.mapper.UserMapper;
import com.example.houseitemmanagebackend.mapper.UserRoleMapper;
import com.example.houseitemmanagebackend.security.JwtUserDetails;
import com.example.houseitemmanagebackend.service.AuthService;
import com.example.houseitemmanagebackend.service.LocationService;
import com.example.houseitemmanagebackend.service.UserLocationService;
import com.example.houseitemmanagebackend.utils.JwtUtil;
import com.example.houseitemmanagebackend.utils.RedisConstants;
import com.example.houseitemmanagebackend.vo.TokenVO;
import com.example.houseitemmanagebackend.vo.UserVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.beans.factory.annotation.Value;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.Base64;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import lombok.extern.slf4j.Slf4j;

/**
 * 认证服务实现类
 */
@Slf4j
@Service
public class AuthServiceImpl implements AuthService {

    private final AuthenticationManager authenticationManager;
    private final JwtUtil jwtUtil;
    private final UserMapper userMapper;
    private final RoleMapper roleMapper;
    private final UserRoleMapper userRoleMapper;
    private final PasswordEncoder passwordEncoder;
    private final LocationService locationService;
    private final UserLocationService userLocationService;

    @Value("${file.upload-dir:D:/app/cursor/houseItemManage/houseItemManage-Front/house-item-manage/images}")
    private String uploadDir;

    public AuthServiceImpl(AuthenticationManager authenticationManager, JwtUtil jwtUtil, UserMapper userMapper,
            RoleMapper roleMapper, UserRoleMapper userRoleMapper, PasswordEncoder passwordEncoder,
            StringRedisTemplate stringRedisTemplate, LocationService locationService,
            UserLocationService userLocationService) {
        this.authenticationManager = authenticationManager;
        this.jwtUtil = jwtUtil;
        this.userMapper = userMapper;
        this.roleMapper = roleMapper;
        this.userRoleMapper = userRoleMapper;
        this.passwordEncoder = passwordEncoder;
        this.locationService = locationService;
        this.userLocationService = userLocationService;
    }

    @Override
    public TokenVO login(LoginDTO loginDTO) {
        // 认证用户
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(loginDTO.getUsername(), loginDTO.getPassword()));

        SecurityContextHolder.getContext().setAuthentication(authentication);
        JwtUserDetails userDetails = (JwtUserDetails) authentication.getPrincipal();

        // 生成JWT令牌
        String token = jwtUtil.generateToken(userDetails);

        // 更新用户最后登录时间
        Users users = userMapper.selectById(userDetails.getId());
        users.setLastLogin(LocalDateTime.now());
        userMapper.updateById(users);

        // 构建用户信息
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(users, userVO);

        return new TokenVO(token, "Bearer", userVO);
    }

    @Override
    @Transactional
    public void register(RegisterDTO registerDTO) {
        // 验证密码是否一致
        if (!registerDTO.getPassword().equals(registerDTO.getConfirmPassword())) {
            throw new BusinessException("两次输入的密码不一致");
        }

        // 验证用户名是否已存在
        if (userMapper.selectCount(new LambdaQueryWrapper<Users>()
                .eq(Users::getUsername, registerDTO.getUsername())) > 0) {
            throw new BusinessException("用户名已存在");
        }

        // 验证邮箱是否已存在
        if (registerDTO.getEmail() != null && userMapper.selectCount(new LambdaQueryWrapper<Users>()
                .eq(Users::getEmail, registerDTO.getEmail())) > 0) {
            throw new BusinessException("邮箱已被注册");
        }

        // 创建用户
        Users users = new Users();
        users.setUsername(registerDTO.getUsername());
        users.setPassword(passwordEncoder.encode(registerDTO.getPassword()));
        users.setNickname(registerDTO.getNickname());
        users.setEmail(registerDTO.getEmail());
        users.setPhone(registerDTO.getPhone());
        users.setStatus(1);
        users.setCreatedAt(LocalDateTime.now());
        users.setUpdatedAt(LocalDateTime.now());

        userMapper.insert(users);

        // 分配用户角色（默认为"USER"角色）
        Role userRole = roleMapper.selectOne(new LambdaQueryWrapper<Role>()
                .eq(Role::getName, "USER"));

        if (userRole != null) {
            UserRole userRoleRelation = new UserRole();
            userRoleRelation.setUserId(users.getId());
            userRoleRelation.setRoleId(userRole.getId());
            userRoleMapper.insert(userRoleRelation);
        }

        // 为新注册用户创建一个名为"家"的默认位置
        try {
            // 创建位置，获取位置ID
            Integer homeLocationId = locationService.addLocation("家", users.getId());

            // 将用户设置为该位置的管理员 (roleType=1 表示管理员)
            userLocationService.addUserToLocation(users.getId(), homeLocationId, 1);

            log.info("已为用户 {} (ID: {}) 创建默认位置'家'，位置ID: {}",
                    users.getUsername(), users.getId(), homeLocationId);
        } catch (Exception e) {
            log.error("为用户 {} (ID: {}) 创建默认位置失败: {}",
                    users.getUsername(), users.getId(), e.getMessage());
            // 不抛出异常，确保用户注册过程不会因为创建位置失败而回滚
        }
    }

    @Override
    public UserVO getCurrentUser(Long userId,Long locationId) {
        // 查询用户信息
        Users users = userMapper.selectById(userId);
        if (users == null) {
            throw new BusinessException("用户不存在");
        }

        //查询角色
        LambdaQueryWrapper<UserLocation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserLocation::getUserId, users.getId()).eq(UserLocation::getLocationId, locationId);
        UserLocation userLocation=userLocationService.getOne(wrapper);
        // 构建用户视图对象
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(users, userVO);
        // 处理字段名称不同的情况
        userVO.setNickname(users.getNickname());
        userVO.setCreateTime(users.getCreatedAt());
        userVO.setLastLoginTime(users.getLastLogin());
        //0-访客，1-管理员，2-管理者，3-成员
        String role="";
        if(userLocation.getRoleType()==1){
            role="管理员";
        }else if(userLocation.getRoleType()==2){
            role="管理者";
        }else  if(userLocation.getRoleType()==3){
            role="成员";
        }else
            role="访客";
        userVO.setRole(role);
        return userVO;
    }

    @Override
    @Transactional
    public void updateProfile(UserProfileDTO userProfileDTO) {
        // 获取当前用户信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null) {
            throw new BusinessException("用户未登录");
        }

        JwtUserDetails userDetails = (JwtUserDetails) authentication.getPrincipal();
        Users users = userMapper.selectById(userDetails.getId());
        if (users == null) {
            throw new BusinessException("用户不存在");
        }

        // 更新用户信息
        if (userProfileDTO.getUsername() != null && !userProfileDTO.getUsername().equals(users.getUsername())) {
            // 检查用户名是否已存在
            if (userMapper.selectCount(new LambdaQueryWrapper<Users>()
                    .eq(Users::getUsername, userProfileDTO.getUsername())
                    .ne(Users::getId, users.getId())) > 0) {
                throw new BusinessException("用户名已存在");
            }
            users.setUsername(userProfileDTO.getUsername());
        }

        if (userProfileDTO.getEmail() != null && !userProfileDTO.getEmail().equals(users.getEmail())) {
            // 检查邮箱是否已存在
            if (userMapper.selectCount(new LambdaQueryWrapper<Users>()
                    .eq(Users::getEmail, userProfileDTO.getEmail())
                    .ne(Users::getId, users.getId())) > 0) {
                throw new BusinessException("邮箱已被注册");
            }
            users.setEmail(userProfileDTO.getEmail());
        }

        if (userProfileDTO.getPhone() != null) {
            users.setPhone(userProfileDTO.getPhone());
        }

        if (userProfileDTO.getNickname() != null) {
            users.setNickname(userProfileDTO.getNickname());
        }

        if (userProfileDTO.getAvatar() != null) {
            String base64Avatar = userProfileDTO.getAvatar();
            boolean isLikelyFilename = !base64Avatar.contains(",") && !base64Avatar.contains(";")
                    && base64Avatar.length() < 255 && base64Avatar.contains(".");

            if (base64Avatar.startsWith("data:image")) {
                try {
                    String[] parts = base64Avatar.split(",");
                    if (parts.length != 2) {
                        throw new BusinessException("无效的头像数据格式");
                    }
                    String imageTypePart = parts[0];
                    String base64Data = parts[1];

                    String extension = ".png";
                    if (imageTypePart.contains("image/jpeg")) {
                        extension = ".jpg";
                    } else if (imageTypePart.contains("image/gif")) {
                        extension = ".gif";
                    } else if (imageTypePart.contains("image/webp")) {
                        extension = ".webp";
                    }

                    byte[] imageBytes = Base64.getDecoder().decode(base64Data);
                    String filename = UUID.randomUUID().toString() + extension;

                    File directory = new File(this.uploadDir);
                    if (!directory.exists()) {
                        if (directory.mkdirs()) {
                            log.info("创建头像上传目录: {}", directory.getAbsolutePath());
                        } else {
                            log.error("无法创建头像上传目录: {}", directory.getAbsolutePath());
                            throw new BusinessException("无法创建头像上传目录");
                        }
                    }

                    String fullPath = Paths.get(this.uploadDir, filename).toString();
                    try (FileOutputStream fos = new FileOutputStream(fullPath)) {
                        fos.write(imageBytes);
                    }

                    users.setAvatar(filename);
                    log.info("用户 {} 头像已更新，新头像文件: {}", users.getUsername(), filename);

                } catch (IllegalArgumentException e) {
                    log.error("Base64解码头像失败 for user {}: {}", users.getUsername(), e.getMessage());
                    throw new BusinessException("头像数据无效，无法解码");
                } catch (IOException e) {
                    log.error("保存头像文件失败 for user {}: {}", users.getUsername(), e.getMessage());
                    throw new BusinessException("保存头像文件失败");
                }
            } else if (isLikelyFilename) {
                if (!base64Avatar.equals(users.getAvatar())) {
                    users.setAvatar(base64Avatar);
                    log.info("用户 {} 头像设置为文件名: {}", users.getUsername(), base64Avatar);
                }
            } else {
                log.warn("用户 {} 提供的头像数据格式未知: {}", users.getUsername(),
                        base64Avatar.substring(0, Math.min(base64Avatar.length(), 50)));
            }
        } else if (userProfileDTO.getAvatar() == null) {
            // If avatar is explicitly set to null in DTO, it might mean "remove avatar"
            // TODO: Implement avatar removal logic if needed (e.g., delete file and clear
            // field)
        }

        users.setUpdatedAt(LocalDateTime.now());
        userMapper.updateById(users);
    }

    String storedCode;

    @Override
    public void sendResetCode(String email) {
        Users user = userMapper.selectOne(new LambdaQueryWrapper<Users>().eq(Users::getEmail, email));
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 生成6位验证码
        storedCode = String.format("%06d", new Random().nextInt(999999));
        log.info("为邮箱 {} 生成的重置密码验证码为: {}", email, storedCode);

    }

    @Override
    public void resetPassword(ResetPasswordDTO resetPasswordDTO) {
        String email = resetPasswordDTO.getEmail();
        String code = resetPasswordDTO.getCaptcha();
        String newPassword = resetPasswordDTO.getNewPassword();

        Users user = userMapper.selectOne(new LambdaQueryWrapper<Users>().eq(Users::getEmail, email));
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        if (!storedCode.equals(code)) {
            throw new BusinessException("验证码错误");
        }

        user.setPassword(passwordEncoder.encode(newPassword));
        userMapper.updateById(user);
    }

    @Override
    public void changePassword(ChangePasswordDTO changePasswordDTO) {
        // 获取用户信息
        Users user = userMapper.selectById(changePasswordDTO.getUserId());
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        // 验证旧密码
        if (!passwordEncoder.matches(changePasswordDTO.getOldPassword(), user.getPassword())) {
            throw new BusinessException("旧密码不正确");
        }

        // 设置新密码
        user.setPassword(passwordEncoder.encode(changePasswordDTO.getNewPassword()));
        user.setUpdatedAt(LocalDateTime.now());

        // 更新用户信息
        userMapper.updateById(user);

        log.info("用户 {} (ID: {}) 成功修改密码", user.getUsername(), user.getId());
    }
}